import logging
import re
import subprocess

from PyQt5.QtCore import Qt, QThreadPool
from PyQt5.QtGui import QTextCursor, QFont
from PyQt5.QtWidgets import QGridLayout, QPushButton, QPlainTextEdit, QLabel, QLineEdit, QInputDialog, \
    QFileDialog, QMessageBox, QTableWidget, QTableWidgetItem, QHeaderView, QDialog, QSplitter, QWidget, \
    QVBoxLayout, QAbstractItemView

from modules.config import hostname_expression, version, ip_expression
from modules.design import TableCheckBox, get_name_with_next_number
from modules.hosts import Hosts
from modules.known_hosts_management import KnownHostsManagement
from modules.system import user, CompKabSolutionWindow, users_admins_generator, run_command
from modules.workers import SSHRootSetup, NetworkFolderSetup, VeyonSetup, \
    SSHCommandInThreads, PingTest


class SettingsWindow(CompKabSolutionWindow):
    def __init__(self):
        super().__init__()

        upper_widget = QWidget()

        self.hosts = Hosts()
        grid = QGridLayout()
        upper_widget.setLayout(grid)
        self.setWindowTitle(f'Настройка компьютерного кабинета, версия {version}')
        self.setMinimumWidth(1000)

        self.textfield = QPlainTextEdit()
        self.textfield.cursor = QTextCursor()
        self.textfield.setReadOnly(True)

        splitter = QSplitter()
        splitter.setOrientation(Qt.Vertical)
        splitter.addWidget(upper_widget)
        splitter.addWidget(self.textfield)

        vboxlayout = QVBoxLayout()
        vboxlayout.addWidget(splitter)
        self.setLayout(vboxlayout)

        grid.setColumnStretch(0, 0)
        grid.setColumnStretch(1, 1)

        hostslabel = QLabel('Список устройств:')
        hostslabel.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        grid.addWidget(hostslabel, 0, 1)

        generate_admins_btn = QPushButton('Генерация админов')
        generate_admins_btn.clicked.connect(self.generate_admins)
        generate_admins_btn.setToolTip('Позволяет задать одинаковые имена пользователей и пароли '
                                       'для админов на компьютерах учеников')
        grid.addWidget(generate_admins_btn, 0, 5)

        generate_users_btn = QPushButton('Генерация пользователей')
        generate_users_btn.clicked.connect(self.generate_users)
        generate_users_btn.setToolTip('Позволяет задать одинаковые имена пользователей и пароли '
                                      'для пользователей на компьютерах учеников')
        grid.addWidget(generate_users_btn, 0, 6)

        # open_filebtn = QPushButton('Открыть файл...')
        # open_filebtn.clicked.connect(self.open_file_dialog)
        # grid.addWidget(open_filebtn, 0, 3)
        # open_filebtn.setDisabled(True)
        # FIXME нужен ли импорт?

        self.hosts_table = QTableWidget()
        self.hosts_table.setColumnCount(9)

        self.update_data(key='load')

        self.hosts_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        grid.addWidget(self.hosts_table, 1, 1, 9, 6)
        self.hosts_table.itemChanged.connect(self.change_data)

        button = QPushButton('Добавить строку')
        button.clicked.connect(self.add_row)
        button.setToolTip('Добавить строку в таблицу')

        grid.addWidget(button, 0, 2)

        button = QPushButton('Удалить строку')
        button.clicked.connect(self.delete_row)
        button.setToolTip('Удалить текущую строку в таблице')
        grid.addWidget(button, 0, 3)

        button = QPushButton('Очистить...')
        button.clicked.connect(self.delete_all)
        button.setToolTip('Очистить таблицу')
        grid.addWidget(button, 0, 4)

        if user == 'root':
            logging.info("Попытка запустить от рута")
            messageBox = QMessageBox.warning(
                self,
                "Неверный пользователь!",
                f"Данное приложение не следует запускать от имени суперпользователя",
                QMessageBox.Ok,
            )
            if messageBox == QMessageBox.Ok:
                self.close()
        elif user == 'student':
            logging.info("Попытка запустить от студента")
            messageBox = QMessageBox.warning(
                self,
                "Неверный пользователь!",
                f"Данное приложение не следует запускать от имени ученика",
                QMessageBox.Ok,
            )
            if messageBox == QMessageBox.Ok:
                self.close()
        else:
            self.button_ping = QPushButton('Проверить ping')
            self.button_ping.clicked.connect(self.test_ping)
            grid.addWidget(self.button_ping, 0, 0)

            self.button_ssh = QPushButton('Настроить доступ по ssh')
            self.button_ssh.clicked.connect(self.setup_ssh)
            grid.addWidget(self.button_ssh, 1, 0)

            self.button_removessh = QPushButton('Удалить ключи ssh')
            self.button_removessh.clicked.connect(self.delete_ssh)
            grid.addWidget(self.button_removessh, 2, 0)

            self.button_create_student = QPushButton('Создать учётные записи учеников')
            self.button_create_student.clicked.connect(self.create_student)
            grid.addWidget(self.button_create_student, 3, 0)

            self.autologin_enable = QPushButton('Включить автологин учеников')
            self.autologin_enable.clicked.connect(self.autologin_enable_func)
            grid.addWidget(self.autologin_enable, 4, 0)

            self.autologin_disable = QPushButton('Выключить автологин учеников')
            self.autologin_disable.clicked.connect(self.autologin_disable_func)
            grid.addWidget(self.autologin_disable, 5, 0)

            self.button_share = QPushButton('Создать сетевую папку')
            self.button_share.clicked.connect(self.network_folders)
            grid.addWidget(self.button_share, 6, 0)

            self.button_veyon = QPushButton('Установить Veyon')
            self.button_veyon.clicked.connect(self.install_veyon)
            grid.addWidget(self.button_veyon, 7, 0)

            self.command_exec = QPushButton('Выполнить команду от админа')
            self.command_exec.clicked.connect(self.run_command_on_ssh)
            grid.addWidget(self.command_exec, 8, 0)

            self.root_command_exec = QPushButton('Выполнить команду от root')
            self.root_command_exec.clicked.connect(self.run_root_command_on_ssh)
            grid.addWidget(self.root_command_exec, 9, 0)

            if len(self.hosts.items_to_list()) == 0:
                self.set_buttons_status(False)

            self.hosts_table.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
            self.hosts_table.horizontalHeader().setStretchLastSection(QHeaderView.Stretch)
            # self.hosts_table.setEditTriggers(QAbstractItemView.CurrentChanged)
            self.hosts_table.setEditTriggers(QAbstractItemView.AllEditTriggers)
            self.hosts_table.horizontalHeader().sectionClicked.connect(self.select_comps)
            # settings_window_menu_bar = QMenuBar()
            # settings_menu = settings_window_menu_bar.addMenu('Меню')
            # import_from_file_menu = settings_menu.addAction('Открыть файл')
            # get_known_hosts_menu = settings_menu.addAction('Импорт из конфига')
            # import_from_file_menu.triggered.connect(self.open_file_dialog)
            # get_known_hosts_menu.triggered.connect(self.import_known_hosts)
            # grid.setMenuBar(settings_window_menu_bar)
            self.commands_history = []

    def generate_admins(self):
        get_data_window = users_admins_generator(True)
        if get_data_window.exec() == QDialog.Accepted:
            name, passwd = get_data_window.name.text(), get_data_window.password.text()
            for row in range(self.hosts_table.rowCount()):
                if self.hosts_table.cellWidget(row, 0).state():
                    if self.hosts_table.item(row, 6):
                        self.hosts_table.item(row, 6).setText(name)
                    else:
                        self.hosts_table.setItem(row, 6, QTableWidgetItem(name))
                    if self.hosts_table.item(row, 7):
                        self.hosts_table.item(row, 7).setText(passwd)
                    else:
                        self.hosts_table.setItem(row, 7, QTableWidgetItem(passwd))

    def generate_users(self):
        get_data_window = users_admins_generator(False)
        if get_data_window.exec() == QDialog.Accepted:
            name, passwd = get_data_window.name.text(), get_data_window.password.text()
            for row in range(self.hosts_table.rowCount()):
                if self.hosts_table.cellWidget(row, 0).state():
                    if self.hosts_table.item(row, 4):
                        self.hosts_table.item(row, 4).setText(name)
                    else:
                        self.hosts_table.setItem(row, 4, QTableWidgetItem(name))
                    if self.hosts_table.item(row, 5):
                        self.hosts_table.item(row, 5).setText(passwd)
                    else:
                        self.hosts_table.setItem(row, 5, QTableWidgetItem(passwd))

    def set_buttons_status(self, status: bool):
        self.button_ping.setEnabled(status)
        self.button_ssh.setEnabled(status)
        self.button_removessh.setEnabled(status)
        self.button_create_student.setEnabled(status)
        self.button_share.setEnabled(status)
        self.button_veyon.setEnabled(status)
        self.command_exec.setEnabled(status)
        self.root_command_exec.setEnabled(status)
        self.autologin_disable.setEnabled(status)
        self.autologin_enable.setEnabled(status)

    def update_data(self, key=None):
        self.hosts_table.blockSignals(True)
        font = QFont()
        font.setUnderline(True)
        font_ip = QFont()
        font_ip.setItalic(True)
        self.hosts_table.setHorizontalHeaderLabels(["Выбор", "Название", "Адрес", 'Мак-адрес', 'Логин ученика',
                                                    'Пароль ученика', 'Логин админа', 'Пароль админа', "Настроен"])
        self.hosts_table.setRowCount(len(self.hosts))

        if key == 'load':
            for index, host in enumerate(self.hosts.items_to_list()):
                item_name = QTableWidgetItem(host.name)
                item_hostname = QTableWidgetItem(host.hostname)
                if re.match(hostname_expression, host.hostname):
                    item_hostname.setFont(font)
                if re.match(ip_expression, host.hostname):
                    item_hostname.setFont(font_ip)
                self.hosts_table.setItem(index, 1, item_name)
                self.hosts_table.setItem(index, 2, item_hostname)
                properties = [host.mac_address, host.student_login, host.student_pass, host.admin_login,
                              host.admin_pass, 'Да' if host.setup else 'Нет']
                for i in range(len(properties)):
                    self.hosts_table.setItem(index, i + 3, QTableWidgetItem(str(properties[i])))
                    if i + 3 in (5, 7):
                        self.hosts_table.item(index, i + 3).setText(
                            '*' * len(self.hosts_table.item(index, i + 3).text()))
                        self.hosts_table.item(index, i + 3).setToolTip(
                            host.student_pass if i + 3 == 5 else host.admin_pass
                        )
                self.hosts_table.item(index, 8).setFlags(Qt.ItemIsEnabled)
                item = TableCheckBox()
                self.hosts_table.setCellWidget(index, 0, item)
                self.hosts_table.cellWidget(index, 0).set_state(2 if host.checked else 0)
                self.hosts_table.cellWidget(index, 0).checkbox.stateChanged.connect(
                    lambda: self.change_data(self.hosts_table.item(10000, 3)))

        # elif key.column() == 2:
        #     if re.match(ip_expression, key.text()):
        #         key.setFont(font_ip)
        #     else:
        #         key.setText(key.text().replace('.local', '') + '.local')
        #         key.setFont(font)
        #
        # elif key.column() in (5, 7):
        #     key.setToolTip(key.text())
        #     key.setText('*' * len(key.text()))
        for row in range(self.hosts_table.rowCount()):
            if self.hosts_table.item(row, 2):
                if re.match(ip_expression, self.hosts_table.item(row, 2).text()):
                    self.hosts_table.item(row, 2).setFont(font_ip)
                elif self.hosts_table.item(row, 2).text() != '':
                    self.hosts_table.item(row, 2).setText(
                        self.hosts_table.item(row, 2).text().replace('.local', '') + '.local')
                    self.hosts_table.item(row, 2).setFont(font)
            if self.hosts_table.item(row, 5):
                self.hosts_table.item(row, 5).setToolTip(self.hosts[self.hosts_table.item(row, 1).text()].student_pass)
                self.hosts_table.item(row, 5).setText('*' * len(self.hosts_table.item(row, 5).text()))
            if self.hosts_table.item(row, 7):
                self.hosts_table.item(row, 7).setToolTip(self.hosts[self.hosts_table.item(row, 1).text()].admin_pass)
                self.hosts_table.item(row, 7).setText('*' * len(self.hosts_table.item(row, 7).text()))
        self.hosts_table.blockSignals(False)

    def change_data(self, item: QTableWidgetItem):
        """
        Реагирует на изменение данных в таблице
        :param item: элемент таблицы
        """

        # FIXME это очень плохое решение
        if not item:  # row = 10000, to update checked
            for row in range(self.hosts_table.rowCount()):
                if self.hosts[self.hosts_table.item(row, 1).text()].checked \
                        is not self.hosts_table.cellWidget(row, 0).state():
                    self.hosts.set_checked(
                        self.hosts_table.item(row, 1).text(), self.hosts_table.cellWidget(row, 0).state())
            return
        item_index = item.row()
        key = self.hosts_table.item(item_index, 1).text()
        old_key = "Введите название" if item_index >= len(self.hosts.to_list()) else self.hosts.to_list()[item_index]
        other_keys = []
        for row in range(self.hosts_table.rowCount()):
            if row != item_index and self.hosts_table.item(row, 1):
                other_keys.append(self.hosts_table.item(row, 1).text())
        done = True
        while key in other_keys:
            key, done = QInputDialog.getText(
                self, 'Внимание', f'Компьютер {key} уже есть в списке.\nВведите новое имя: ')
        if not done:
            key = old_key
            if key == "Введите название":
                key = ""
        hostname = self.hosts_table.item(item_index, 2).text() if self.hosts_table.item(item_index, 2) else ""
        if hostname.endswith('.local'):
            hostname = hostname.replace('.local', '') + '.local'
        checked = self.hosts_table.cellWidget(item_index, 0).state() if self.hosts_table.cellWidget(item_index, 0) \
            else True
        mac_address = self.hosts_table.item(item_index, 3).text() if self.hosts_table.item(item_index, 3) else ""
        student_login = self.hosts_table.item(item_index, 4).text() if self.hosts_table.item(item_index, 4) else ""
        student_pass = self.hosts_table.item(item_index, 5).text() if item.column() == 5 else \
            (self.hosts[key].student_pass if key in self.hosts.to_list() else
             (self.hosts[old_key].student_pass if old_key in self.hosts.to_list() else ""))
        admin_login = self.hosts_table.item(item_index, 6).text() if self.hosts_table.item(item_index, 6) else ""
        admin_pass = self.hosts_table.item(item_index, 7).text() if item.column() == 7 else \
            (self.hosts[key].admin_pass if key in self.hosts.to_list() else
             (self.hosts[old_key].admin_pass if old_key in self.hosts.to_list() else ""))
        setup = True if self.hosts_table.item(item_index, 8) and self.hosts_table.item(item_index, 8).text() == 'Да' \
            else False
        if key != '':
            self.hosts.set_item(key, hostname, mac_address, student_login, student_pass, admin_login, admin_pass, setup,
                                checked)
            if self.hosts_table.item(item.row(), 8):
                self.hosts_table.item(item.row(), 8).setText('Да' if self.hosts[key].setup else 'Нет')
        for host in self.hosts.items_to_list():
            if host.name not in other_keys + [key]:
                del self.hosts[host.name]
        if item.column() == 1:
            self.hosts_table.item(item.row(), 1).setText(key)
        self.update_data(item)

    def add_row(self):
        """
        Добавление пустой строки
        """
        hostnames = [host.name for host in self.hosts.items_to_list()]
        number = self.hosts_table.rowCount()
        item_name = "Введите название"
        if self.hosts_table.currentItem() and self.hosts_table.currentColumn() == 1:
            current_name = self.hosts_table.currentItem().text()
            item_name = get_name_with_next_number(current_name)
        # done = True
        while item_name in hostnames:
            #     item_name, done = QInputDialog.getText(
            #         self, 'Внимание', f'Компьютер {item_name} уже есть в списке.\nВведите новое имя: ')
            # if not done or item_name == '':
            #     return
            item_name = get_name_with_next_number(item_name)
        self.hosts_table.setRowCount(number + 1)
        self.hosts_table.setItem(number, 1, QTableWidgetItem(item_name))
        self.hosts_table.setItem(number, 8, QTableWidgetItem('Нет'))
        self.hosts_table.item(number, 8).setFlags(Qt.ItemIsEnabled)
        self.hosts_table.setCellWidget(number, 0, TableCheckBox())
        self.hosts_table.cellWidget(number, 0).set_state(2)
        self.hosts_table.cellWidget(number, 0).checkbox.stateChanged.connect(
            lambda: self.change_data(self.hosts_table.item(10000, 3)))
        self.hosts_table.setCurrentCell(number, 1)
        self.set_buttons_status(True)

    def delete_row(self):
        """
        Удаление строки и удаление из файла
        """
        row = self.hosts_table.currentRow()
        if row < 0:
            return
        else:
            key = self.hosts_table.item(row, 1).text()
            messageBox = QMessageBox.warning(
                self,
                "Подтверждение удаления!",
                f"Вы действительно хотите удалить {key}?",
                QMessageBox.Ok | QMessageBox.Cancel,
            )
            if messageBox == QMessageBox.Ok:
                if key in self.hosts.hosts:
                    del self.hosts[key]
                self.hosts_table.removeRow(row)
        if len(self.hosts.items_to_list()) == 0:
            self.set_buttons_status(False)

    def delete_all(self):
        """
        Очистка таблицы и удаление из файла
        """
        message_box = QMessageBox.warning(
            self,
            "Подтверждение удаления!",
            f"Вы действительно хотите очистить список устройств?",
            QMessageBox.Ok | QMessageBox.Cancel,
        )
        if message_box == QMessageBox.Ok:
            self.hosts.clean()
            self.update_data(key='load')

    def select_comps(self, item):
        if item == 0:
            status = 0
            for i in range(len(self.hosts.items_to_list())):
                if self.hosts_table.cellWidget(i, 0).state() == 0:
                    status = 2
                    break
            for i in range(len(self.hosts.items_to_list())):
                self.hosts_table.cellWidget(i, 0).set_state(status)

    def open_file_dialog(self):
        file_name = QFileDialog.getOpenFileName(
            self,
            directory=f"/home/{user}",
            caption='Импорт из текстового файла',
            filter='*.txt'
        )
        # FIXME getOpenFileName не вызывается
        # file_name = QFileDialog.getOpenFileName(self)
        try:
            with open(file_name[0], 'r') as inp:
                lines = inp.readlines()
                if len(lines) > 1000:
                    QMessageBox('Слишком большой файл!').show()
                else:
                    for index, host in enumerate(lines):
                        new_index = self.hosts_table.rowCount() + 1
                        self.hosts_table.setRowCount(new_index)
                        self.hosts_table.setItem(new_index - 1, 1, QTableWidgetItem(f"Host {index + 1}"))
                        self.hosts_table.setItem(new_index - 1, 2, QTableWidgetItem(host.strip()))
        except FileNotFoundError:
            pass

    def import_known_hosts(self):
        print('importing')
        self.known_hosts_window = KnownHostsManagement()
        self.known_hosts_window.show()

    def update_textfield(self, message):
        self.textfield.appendPlainText(message)

    def test_ping(self):
        self.textfield.clear()

        self.thread = PingTest()
        host_list = []
        for index, host in enumerate(self.hosts.items_to_list()):
            if self.hosts_table.cellWidget(index, 0).state():
                host_list.append(host)
        self.thread.host_list = host_list

        self.textfield.appendPlainText(f"\nПроверка ping, выбрано компьютеров: {len(host_list)}")
        self.thread.progress_signal.connect(self.update_textfield)
        self.thread.finished.connect(self.thread.deleteLater)
        self.thread.start()

        self.set_buttons_status(False)
        self.thread.finished.connect(
            lambda: self.set_buttons_status(True)
        )
        # self.thread.finished.connect(
        #     lambda: self.textfield.appendPlainText("")
        # )

    def setup_ssh(self):
        self.textfield.clear()
        messageBox = QMessageBox.information(
            self,
            "Важная информация!",
            f"Вы запустили настройку ssh для пользователей из группы wheel на компьютерах, указанных в таблице.\n\n"
            f"Во время первичной настройки будет осуществляться подключение к компьютерам "
            f"и сохранение ключей аутентификации для пользователя из wheel.\n",
            # f"Для копирования ключей пользователю root потребуется ввести пароль (предполагается что он единый "
            # f"на всех устройствах)\n\n"
            # f"При сохренении ключей будет необходимо подтвердить действие "
            # f"вводом слова Yes и вводом пароля от teacher на каждом устройстве.",
            QMessageBox.Ok | QMessageBox.Cancel,
        )
        if messageBox == QMessageBox.Ok:
            # root_pass, okPressed = QInputDialog.getText(
            #     self, "Введите пароль root",
            #     f"Введите пароль учётной записи суперпользователя root (для устройств учеников): ",
            #     QLineEdit.Password, "")
            # if okPressed:
            self.thread = SSHRootSetup()

            host_list = []
            for index, host in enumerate(self.hosts.items_to_list()):
                if self.hosts_table.cellWidget(index, 0).state():
                    host_list.append(host)
            self.thread.host_list = host_list
            self.thread.hosts = self.hosts
            # self.thread.root_pass = root_pass

            self.textfield.appendPlainText(f"\nНастройка ssh, выбрано компьютеров: {len(host_list)}")
            self.thread.progress_signal.connect(self.update_textfield)
            self.thread.finished.connect(self.thread.deleteLater)
            self.thread.start()

            self.set_buttons_status(False)
            self.thread.finished.connect(
                lambda: self.set_buttons_status(True)
            )
            # self.thread.finished.connect(
            #     lambda: self.textfield.appendPlainText("\nНастройка SSH завершена.\n")
            # )
            self.thread.finished.connect(self.refill_table)

    def delete_ssh(self):
        self.textfield.clear()
        messageBox = QMessageBox.information(
            self,
            "Внимание!",
            f"Вы собираетесь удалить ключи ssh на компьютерах пользователей",
            QMessageBox.Ok | QMessageBox.Cancel,
        )
        if messageBox == QMessageBox.Ok:
            logging.info('Удаление ключей ssh')
            selected = 0
            for i in range(len(self.hosts.items_to_list())):
                if self.hosts_table.cellWidget(i, 0).state():
                    selected += 1
            self.textfield.appendPlainText(f"\nУдаление ключей ssh, выбрано компьютеров: {selected}")
            cnt = 0
            for index, host in enumerate(self.hosts.items_to_list()):
                if self.hosts_table.cellWidget(index, 0).state():
                    if host.setup is False:
                        self.textfield.appendPlainText(f'\nНа {host.hostname} не настроен ssh')
                        continue
                    result = subprocess.run(['ping', '-c1', host.hostname], stdout=subprocess.PIPE)
                    if result.returncode == 0:
                        self.textfield.appendPlainText(f'\nУдаление ключей на {host.hostname}...')
                        logging.info(f'\nУдаление ключей на {host.hostname}...')
                        run_command(f'ssh root@{host.hostname} rm -rf /root/.ssh /home/{host.admin_login}/.ssh')
                        self.textfield.appendPlainText(f'\nКлючи ssh удалены на {host.hostname}.')
                        self.hosts.set_false_setup(host.hostname)
                        cnt += 1
                    else:
                        self.textfield.appendPlainText(f'\nКомпьютер {host.hostname} недоступен.')
            self.textfield.appendPlainText(f'Удаление ключей ssh с компьютеров пользователей завершено.\n'
                                           f'Успешно обработано компьютеров: {cnt}')

    def create_student(self):
        self.textfield.clear()
        logging.info('Создание учётных записей пользователей')
        selected = 0
        for i in range(len(self.hosts.items_to_list())):
            if self.hosts_table.cellWidget(i, 0).state():
                selected += 1
        self.textfield.appendPlainText(f"\nСоздание учётных записей учеников, выбрано компьютеров: {selected}")
        cnt = 0
        for index, host in enumerate(self.hosts.items_to_list()):
            if self.hosts_table.cellWidget(index, 0).state():
                if host.setup is False:
                    self.textfield.appendPlainText(f'На {host.hostname} не настроен ssh\n')
                    continue
                result = subprocess.run(['ping', '-c1', host.hostname], stdout=subprocess.PIPE)
                if result.returncode == 0:
                    self.textfield.appendPlainText(
                        f'\nСоздание учётной записи {host.student_login} на {host.hostname}...')
                    res = run_command(f'ssh root@{host.hostname} getent passwd {host.student_login}')
                    if res != '':
                        self.textfield.appendPlainText(
                            f'\nНа {host.hostname} уже есть учётная запись пользователя {host.student_login}')
                        logging.info(f'\nНа {host.hostname} уже есть учётная запись пользователя {host.student_login}')
                    else:
                        works_folder = f'install -d -m 0755 -o {host.student_login} -g {host.student_login} \\"/home/{host.student_login}/Рабочий стол/Сдать работы\\"'
                        command = f'echo \'' \
                                  f'useradd {host.student_login} && ' \
                                  f'chpasswd <<<\'{host.student_login}:{host.student_pass}\' && ' \
                                  f'{works_folder}\' | at now'
                        run_command(f'ssh root@{host.hostname} \"{command}\"')
                        self.textfield.appendPlainText(f'{host.hostname}: {host.student_login} создан')
                        logging.info(f'{host.hostname} {host.student_login} создан')
                        cnt += 1
                else:
                    self.textfield.appendPlainText(
                        f'\nКомпьютер {host.hostname} недоступен.')
        self.textfield.appendPlainText(
            f'\nСоздание учётных записей учеников завершено.\n'
            f'Успешно компьютеров: {cnt}\n'
            f'Внимание! Перед дальнейшей работой проверьте, что на вновь созданных учётных записях '
            f'присутствует подключение к сети.')

    def network_folders(self):
        self.textfield.clear()
        messageBox = QMessageBox.information(
            self,
            "Важная информация!",
            f"Вы запустили настройку сетевой папки.\n\n"
            f"На компьютере учителя будет создана папка /home/share, "
            f"к которой будет настроен доступ по протоколу smb.",
            QMessageBox.Ok | QMessageBox.Cancel,
        )
        if messageBox == QMessageBox.Ok:
            self.thread = NetworkFolderSetup()
            # self.thread.hosts = self.hosts
            host_list = []
            for index, host in enumerate(self.hosts.items_to_list()):
                if self.hosts_table.cellWidget(index, 0).state():
                    host_list.append(host)
            self.thread.host_list = host_list

            self.textfield.appendPlainText(f"\nНастройка сетевых папок, выбрано компьютеров: {len(host_list)}\n")
            self.thread.progress_signal.connect(self.update_textfield)
            self.thread.finished.connect(self.thread.deleteLater)
            self.thread.start()

            self.set_buttons_status(False)
            self.thread.finished.connect(
                lambda: self.set_buttons_status(True)
            )
            # self.thread.finished.connect(
            #     lambda: self.textfield.appendPlainText("\nНастройка сетевых папок завершена.\n")
            # )

    def install_veyon(self):
        self.textfield.clear()
        kab, okPressed = QInputDialog.getText(self, "Номер кабинета",
                                              f"Введите номер этого кабинета (без пробелов):",
                                              QLineEdit.Normal, "")
        if okPressed:
            self.thread = VeyonSetup()
            self.thread.hosts = self.hosts
            host_list = []
            for index, host in enumerate(self.hosts.items_to_list()):
                if self.hosts_table.cellWidget(index, 0).state():
                    host_list.append(host)
            self.thread.host_list = host_list
            self.thread.kab = kab

            self.thread.started.connect(
                lambda: self.textfield.appendPlainText(
                    f"\nКоманды для настройки Veyon отправлены на компьютеры учеников, "
                    f"выбрано компьютеров: {len(host_list)}.\n"
                    f"Дождитесь перезагрузки устройств.")
            )
            self.thread.progress_signal.connect(self.update_textfield)
            self.thread.finished.connect(self.thread.deleteLater)
            self.thread.start()

            self.set_buttons_status(False)
            self.thread.finished.connect(
                lambda: self.set_buttons_status(True)
            )
            self.thread.finished.connect(self.refill_table)

    def refill_table(self):
        self.hosts_table.clear()
        self.update_data(key='load')

    def run_command_on_ssh(self):
        self.textfield.clear()
        dialog = QInputDialog(self)
        dialog.setWindowTitle('Команда')
        dialog.setLabelText('Введите команду для выполнения на компьютерах учеников')
        dialog.setInputMode(QInputDialog.TextInput)
        dialog.setComboBoxItems(self.commands_history)
        dialog.setComboBoxEditable(True)
        dialog.setTextValue('')
        if dialog.exec_() == QDialog.Accepted:
            command = dialog.textValue()
            self.commands_history.append(command)
            self.update_textfield(f"Начало выполнения команды:\n{command}")
            selected = 0
            for i in range(len(self.hosts.items_to_list())):
                if self.hosts_table.cellWidget(i, 0).state():
                    selected += 1
            self.textfield.appendPlainText(f"\nВыбрано компьютеров: {selected}")
            pool = QThreadPool.globalInstance()
            cnt = 0
            for index, host in enumerate(self.hosts.items_to_list()):
                if self.hosts_table.cellWidget(index, 0).state():
                    if host.setup is True and subprocess.run(['ping', '-c1', host.hostname],
                                                             stdout=subprocess.PIPE).returncode == 0:
                        runnable = SSHCommandInThreads(host, command)
                        runnable.progress_signal.signal.connect(self.update_textfield)
                        pool.start(runnable)
                        cnt += 1
                    else:
                        self.textfield.appendPlainText(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
                        logging.info(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
            self.update_textfield(f"Выполнение команды {command} завершено.\nУспешно компьютеров: {cnt}")

    def run_root_command_on_ssh(self):
        self.textfield.clear()
        dialog = QInputDialog(self)
        dialog.setWindowTitle('Команда')
        dialog.setLabelText('Введите команду для выполнения от root на компьютерах учеников')
        dialog.setInputMode(QInputDialog.TextInput)
        dialog.setComboBoxItems(self.commands_history)
        dialog.setComboBoxEditable(True)
        dialog.setTextValue('')
        if dialog.exec_() == QDialog.Accepted:
            command = dialog.textValue()
            self.commands_history.append(command)
            selected = 0
            for i in range(len(self.hosts.items_to_list())):
                if self.hosts_table.cellWidget(i, 0).state():
                    selected += 1
            self.textfield.appendPlainText(f"\nНачало выполнения {command} от root.\nВыбрано компьютеров: {selected}")
            cnt = 0
            for index, host in enumerate(self.hosts.items_to_list()):
                if self.hosts_table.cellWidget(index, 0).state():
                    if host.setup is True and subprocess.run(['ping', '-c1', host.hostname],
                                                             stdout=subprocess.PIPE).returncode == 0:
                        res = run_command(f'ssh root@{host.hostname} {command}')
                        self.textfield.appendPlainText(
                            f'\nРезультат выполнения {command} на root@{host.hostname}: {res}\n')
                        cnt += 1
                    else:
                        self.textfield.appendPlainText(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
                        logging.info(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
            self.textfield.appendPlainText(f'Команда {command} выполнена.\nУспешно компьютеров: {cnt}')

    def autologin_enable_func(self):
        self.textfield.clear()
        selected = 0
        for i in range(len(self.hosts.items_to_list())):
            if self.hosts_table.cellWidget(i, 0).state():
                selected += 1
        self.textfield.appendPlainText(f"\nВключение автологина. Выбрано компьютеров: {selected}")
        cnt = 0
        for index, host in enumerate(self.hosts.items_to_list()):
            if self.hosts_table.cellWidget(index, 0).state():
                if host.setup is True and subprocess.run(['ping', '-c1', host.hostname],
                                                         stdout=subprocess.PIPE).returncode == 0:
                    self.textfield.appendPlainText(f'\nВключение автологина на {host.hostname}...\n')
                    run_command(
                        f'ssh root@{host.hostname} '
                        f'py-ini-config set /etc/sddm.conf Autologin User {host.student_login}')
                    self.textfield.appendPlainText(f'\nАвтологин {host.student_login} на {host.hostname} включён\n')
                    cnt += 1
                else:
                    self.textfield.appendPlainText(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
                    logging.info(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
        self.textfield.appendPlainText(f'Включение автологинов учеников завершено.\nУспешно компьютеров: {cnt}')

    def autologin_disable_func(self):
        self.textfield.clear()
        selected = 0
        for i in range(len(self.hosts.items_to_list())):
            if self.hosts_table.cellWidget(i, 0).state():
                selected += 1
        self.textfield.appendPlainText(f"\nВыключение автологина. Выбрано компьютеров: {selected}")
        cnt = 0
        for index, host in enumerate(self.hosts.items_to_list()):
            if self.hosts_table.cellWidget(index, 0).state():
                if host.setup is True and subprocess.run(['ping', '-c1', host.hostname],
                                                         stdout=subprocess.PIPE).returncode == 0:
                    self.textfield.appendPlainText(f'\nВыключение автологина на {host.hostname}...\n')
                    run_command(
                        f'ssh root@{host.hostname} py-ini-config del /etc/sddm.conf Autologin User --flush')
                    self.textfield.appendPlainText(f'\nАвтологин {host.student_login} на {host.hostname} выключен\n')
                    cnt += 1
                else:
                    self.textfield.appendPlainText(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
                    logging.info(f'\nНа {host.hostname} не настроен ssh или он не в сети.')
        self.textfield.appendPlainText(f'Выключение автологинов учеников завершено.\nУспешно компьютеров: {cnt}')
